import Toast from "./common/Toast";
import audioManager from "./common/AudioManager";
import toastManager from "./common/ToastManager";
import {Http, http} from "./common/Http";
import {isArray, isEmpty, isFunction, isObject} from "./common/Helpers";
import GlobalData from "../store/GlobalData";


const {ccclass, property} = cc._decorator;

@ccclass
export default class Common extends cc.Component {
    /**
     * 树苗图集
     * @protected
     */
    protected treeAtlas: cc.SpriteAtlas

    /**
     * 按钮点击的水滴声音
     * @protected
     */
    protected audioManager

    /**
     * 提示框管理
     * @protected
     */
    protected toastManager

    protected http: Http


    protected _data = {
        currentScene: 'login', // 当前所在场景
        hasToken: false, // 是否登录
        userInfo: {}, // 用户信息
        shopGoods: [], // 商城产品列表
        tasks: [], // 每日任务列表
        reUserLists: {}
    }

    protected watch: any = {}

    protected formData: any = {}

    onInput(value, e: cc.EditBox, key) {
        this.formData[key] = value
    }

    protected onLoad() {
        this.http = http
        let isMuteStr = cc.sys.localStorage.getItem('isMute')
        const isMute = isMuteStr && isMuteStr.length
        this.getAudioManager().setIsMute(isMute)
        this.formData = {}
        this._initMvvm()
        const userToken = cc.sys.localStorage.getItem('userToken')
        this._data.hasToken = !isEmpty(userToken)
        this._data.currentScene = cc.director.getScene().name
        if (this._data.hasToken && isEmpty(this._data.userInfo)) {
            this.initUserInfo()
        }
    }

    async initUserInfo(isForce = false) {
        try {
            if (!isForce && !isEmpty(this._data.userInfo)) {
                return this._data.userInfo;
            }
            if (!isForce && !isEmpty(GlobalData.userInfo)) {
                this._data.userInfo = GlobalData.userInfo

                return GlobalData.userInfo;
            }
            const {data} = await this.http.get('auth/getUserInfo')
            GlobalData.userInfo = data;
            this._data.userInfo = data;
            return data
        } catch (e) {

        }
    }

    protected opacityTween(node, show = true, duration = 0.5) {
        node.active = true
        return new Promise((resolve) => {
            const opacity = show ? 255 : 0;
            cc.tween(node).to(duration, {opacity}).call(() => {
                if (!show) {
                    node.active = false
                }
                resolve()
            }).start();
        })
    }

    private _initMvvm() {
        this.node.on('_onDataChange', this._onDataChange, this)
        this._data = this._setObjectProxy(this._data)
    }

    private _setObjectProxy(data, rootPath = '') {
        data = this._setProxy(data, rootPath);
        for (let key in data) {
            const item = data[key];
            if (isObject(item) || isArray(item)) {
                const _itemPath = this._getPathString(key, rootPath)
                data[key] = this._setProxy(item, _itemPath);
                this._setObjectProxy(item, this._getPathString(_itemPath))
            }
        }
        return data;
    }

    private _emitDataChange(key: string, oldValue?: any) {
        const _data = this._data;
        let keyArr: string[] = key.split('.')
        let currentData = _data
        let currentPath = []
        if (isEmpty(keyArr)) {
            return;
        }
        for (let i of keyArr) {
            currentPath.push(i)
            currentData = currentData[i]
            if (!isArray(currentData) && !isObject(currentData)) {
                break;
            }
        }
        let itemKey = currentPath.pop()
        this.node.emit('_onDataChange', itemKey, currentData, currentPath.join('.'), oldValue)

    }

    _onDataChange(key, value, rootPath, oldValue?: any) {
        const _path = this._getPathString(key, rootPath)
        for (let w in this.watch) {
            const callback = this.watch[w]
            if (_path === w && isFunction(callback)) {
                callback.bind(this)(value, oldValue)
            }
        }
        switch (key) {
            case 'currentScene': // 场景切换
                const currentSceneName = cc.director.getScene().name
                if (currentSceneName === 'login') {
                    if (!isEmpty(this._data.userInfo)) {
                        this.schedule(() => {
                            cc.director.loadScene('hall')
                        }, 0.5)
                    } else if (currentSceneName !== value) {
                        this.schedule(() => {
                            cc.director.loadScene(value)
                        }, 1)
                    }

                } else {
                    if (!this._data.hasToken) {
                        this.schedule(() => {
                            cc.director.loadScene('login')
                        }, 1)
                    }
                }


                break;
            case 'userInfo': // 用户信息
                if (!isEmpty(value)) {
                    if (this._data.currentScene === 'login') { // 已登录用户直接前往首页
                        this._data.currentScene = 'hall';
                    }
                }
                break;
        }
    }

    private _getPathString(path, rootPath = '') {
        if (isEmpty(rootPath)) {
            return path
        }
        return `${rootPath}.${path}`
    }

    private _setProxy(data, rootPath = '') {
        return new Proxy(data, {
            set: (target, key: string, value: any) => {
                const oldValue = Reflect.get(target, key)
                let res = true
                if (oldValue !== value) {
                    res = Reflect.set(target, key, value)
                    if (res) {
                        this._emitDataChange(this._getPathString(key, rootPath), oldValue)
                    }
                }
                return res;
            }
        });
    }


    /**
     * 按钮点击事件
     * @protected
     */
    protected onBtnClick() {
        this.getAudioManager().playBtnClickAudio()

    }


    /**
     * 获取树的所有资源图
     */
    async getTreeAtlas() {
        if (this.treeAtlas) {
            return this.treeAtlas
        }
        return new Promise<cc.SpriteAtlas>(resolve => {
            cc.resources.load('tree', cc.SpriteAtlas, (err, assets: cc.SpriteAtlas) => {
                this.treeAtlas = assets
                resolve(assets)
            })
        })
    }

    /**
     * 返回大厅
     */
    goToHall() {
        cc.director.loadScene('hall')
    }

    /**
     * 显示弹框组件
     * @param content
     * @param height
     */
    showToast(content: string, height: number = Toast.height) {
        if (isEmpty(content)) {
            return;
        }
        this.getToastManager().show(content, height)
    }

    closeToast(delay = 0) {
        if (delay <= 0) {
            this.getToastManager().close();
        } else {
            this.schedule(() => {
                this.getToastManager().close();
            }, delay)
        }

    }

    /**
     * 获取/assets/resources/prefabs下的预制体组件
     * @param name
     */
    async getPrefab(name: string) {
        return new Promise<cc.Prefab>(resolve => {
            cc.resources.load(`prefabs/${name}`, cc.Prefab, (err, assets: cc.Prefab) => {
                resolve(assets)
            })
        })
    }

    protected getAudioManager() {
        if (!this.audioManager) {
            this.audioManager = audioManager
        }
        return this.audioManager
    }

    protected getToastManager() {
        if (!this.toastManager) {
            this.toastManager = toastManager
        }
        return this.toastManager
    }
}
